﻿/*
* 创建者：LIYINFAI
* 创建时间：2023/10/24 9:35:26
* 描述：
* --------------------------------------
* 修改说明：
* --------------------------------------
*/
using SQLiteEx;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;

namespace CommonLibrary
{

    /// <summary>
    /// 报警信息实体
    /// </summary>
    [Table("alarms")]
    public class AlarmInfo
    {
        /// <summary>
        /// Id
        /// </summary>
        [PrimaryKey]
        [AutoIncrement]
        [Description("Id")]
        public long Id { get; set; }
        /// <summary>
        /// 报警代码
        /// </summary>
        [Description("报警代码")]
        public string AlarmCode { get; set; }
        /// <summary>
        /// 报警内容
        /// </summary>
        [Description("报警内容")]
        public string AlarmContent { get; set; }
        /// <summary>
        /// 开始时间
        /// </summary>
        [Description("开始时间")]
        public string StartTime { get; set; }
        /// <summary>
        /// 结束时间
        /// </summary>
        [Description("结束时间")]
        public string EndTime { get; set; }
        /// <summary>
        /// 描述信息
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            return CommonHelper.GetObjectString(this);
        }
    }
    /// <summary>
    /// 报警信息数据库操作类
    /// </summary>
    public class AlarmsSQLiteDb : SQLiteHelper
    {
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="dbPath"></param>
        public AlarmsSQLiteDb(string dbPath) : base(dbPath)
        {
        }
        /// <summary>
        /// 单例对象
        /// </summary>
        /// <returns></returns>
        public static AlarmsSQLiteDb Instance()
        {
            string dbFile = Path.Combine(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "dbs"), $"alarms.db");
            CommonHelper.CheckDirectory(dbFile);
            AlarmsSQLiteDb db = null;
            if (CommonHelper.CheckFile(dbFile))
            {
                db = new AlarmsSQLiteDb(dbFile);
                db.CreateTable<AlarmInfo>();
                db.CreateIndex("alarms", new string[] { "StartTime", "EndTime", "AlarmContent" });
            }
            else
            {
                db = new AlarmsSQLiteDb(dbFile);
            }
            return db;
        }

        /// <summary>
        /// 获取一定时间内的报警信息
        /// 若报警信息中出现只有报警开始时间而没有报警结束时间的，在满足时间条件的情况下，会以endTime作为结束时间
        /// 规则如下（或操作）
        /// 1. 报警开始时间在范围内
        /// 2. 报警结束时间在范围内
        /// 3. 报警开始以及结束时间包含了该范围
        /// </summary>
        /// <param name="startTime"></param>
        /// <param name="endTime"></param>
        /// <param name="needFixTimes">是否需要修正返回数据中的开始时间跟结束时间，以传入的startTime 跟 endTime作为基准来修理</param>
        /// <param name="alarmContent"></param>
        /// <returns>alarms 报警数据，minutes 当前时间范围内报警分钟数</returns>
        public static (List<AlarmInfo> alarms, int minutes) GetAlarms(DateTime startTime, DateTime endTime, string alarmContent = "", bool needFixTimes = false)
        {
            List<AlarmInfo> alarmInfos = new List<AlarmInfo>();
            var maxMinutes = (int)Math.Round(endTime.Subtract(startTime).TotalMinutes);
            int minutes = 0;
            var startTimeString = startTime.ToString("yyyy-MM-dd HH:mm:ss");
            var endTimeString = endTime.ToString("yyyy-MM-dd HH:mm:ss");
            if (endTime.Subtract(startTime).TotalSeconds > 0)
            {
                using (AlarmsSQLiteDb db = Instance())
                {
                    var list = db.ToList<AlarmInfo>($"select * from alarms where ((starttime>='{startTimeString}' and starttime<='{endTimeString}')" +
                        $"or (endtime>='{startTimeString}' and endtime<='{endTimeString}')" +
                        $"or (starttime<='{startTimeString}' and endtime>='{endTimeString}')) and (" +
                        $"{(string.IsNullOrWhiteSpace(alarmContent) ? "1=1" : $" AlarmContent like '%{alarmContent}%' ")})");
                    if (list != null && list.Count() > 0)
                    {
                        alarmInfos.AddRange(list);
                    }
                }
            }
            if (alarmInfos.Count > 0 && needFixTimes)
            {
                foreach (var alarmInfo in alarmInfos)
                {
                    alarmInfo.EndTime = string.IsNullOrWhiteSpace(alarmInfo.EndTime) ? endTimeString : alarmInfo.EndTime;
                    alarmInfo.StartTime = string.IsNullOrWhiteSpace(alarmInfo.StartTime) ? startTimeString : alarmInfo.StartTime;

                    alarmInfo.EndTime = DateTime.Parse(alarmInfo.EndTime).Subtract(endTime).TotalSeconds > 0 ? endTimeString : alarmInfo.EndTime;
                    alarmInfo.StartTime = DateTime.Parse(alarmInfo.StartTime).Subtract(startTime).TotalSeconds < 0 ? startTimeString : alarmInfo.StartTime;
                }
            }
            if (alarmInfos.Count > 0)
            {
                DateTime tempTime = startTime;
                while (endTime.Subtract(tempTime).TotalMinutes > 0)
                {
                    if (alarmInfos.Find(v => !string.IsNullOrWhiteSpace(v.StartTime)
                    && !string.IsNullOrWhiteSpace(v.EndTime)
                    && tempTime.Subtract(DateTime.Parse(v.StartTime)).TotalSeconds >= 0 && DateTime.Parse(v.EndTime).Subtract(tempTime).TotalSeconds >= 0) != null)
                    {
                        minutes++;
                    }
                    tempTime = tempTime.AddMinutes(1);
                }
            }
            return (alarmInfos, minutes > maxMinutes ? maxMinutes : minutes);
        }
        /// <summary>
        /// 删除所有没有报警结束时间的记录
        /// </summary>
        public static void ClearEmptyAlarms()
        {
            using (AlarmsSQLiteDb db = Instance())
            {
                var emptyInfos = db.ToList<AlarmInfo>("select * from alarms where EndTime is null or EndTime=''");
                if (emptyInfos != null && emptyInfos.Count() > 0)
                {
                    db.DeleteRange(emptyInfos);
                }
            }
        }
        /// <summary>
        /// 程序退出时，赋予没有结束时间的报警结束时间
        /// </summary>
        public static void EndEmptyAlarms()
        {
            using (AlarmsSQLiteDb db = Instance())
            {
                var emptyInfos = db.ToList<AlarmInfo>($"select * from alarms where EndTime is null or EndTime = ''");
                if (emptyInfos != null && emptyInfos.Count() > 0)
                {
                    string now = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                    foreach (var alarmInfo in emptyInfos)
                    {
                        alarmInfo.EndTime = now;
                    }
                }
            }
        }
        /// <summary>
        /// 增加报警开始记录
        /// </summary>
        /// <param name="code"></param>
        /// <param name="content"></param>
        /// <param name="startTime"></param>
        /// <returns></returns>
        public static bool StartAlarm(string code, string content, string startTime)
        {
            bool result = false;
            DateTime time = DateTime.Now;
            if (!string.IsNullOrWhiteSpace(code)
                && !string.IsNullOrWhiteSpace(content)
                && !string.IsNullOrWhiteSpace(startTime)
                && DateTime.TryParse(startTime, out time))
            {
                using (AlarmsSQLiteDb db = Instance())
                {
                    var emptyInfos = db.ToList<AlarmInfo>($"select * from alarms where AlarmCode='{code}' and AlarmContent='content' and " +
                        $"(EndTime is null or EndTime='')");
                    if (emptyInfos != null && emptyInfos.Count() > 0)
                    {
                        db.DeleteRange(emptyInfos);
                    }
                    db.Insert(new AlarmInfo()
                    {
                        AlarmCode = code,
                        AlarmContent = content,
                        StartTime = startTime
                    });
                    result = true;
                }
            }
            return result;
        }
        /// <summary>
        /// 增加报警结束数据，如果数据库已经有了报警开始的记录，那么就把报警结束的时间写入，如果数据库没有报警开始的记录，那么需要判断传入的开始时间是否有值，若有值则创建新数据
        /// </summary>
        /// <param name="code"></param>
        /// <param name="content"></param>
        /// <param name="endTime"></param>
        /// <param name="startTime"></param>
        /// <returns></returns>
        public static bool EndAlarm(string code, string content, string endTime, string startTime = "")
        {
            bool result = false;
            DateTime time = DateTime.Now;
            if (!string.IsNullOrWhiteSpace(code)
                && !string.IsNullOrWhiteSpace(content)
                && !string.IsNullOrWhiteSpace(endTime)
                && DateTime.TryParse(endTime, out time))
            {
                using (AlarmsSQLiteDb db = Instance())
                {
                    var entity = db.ToList<AlarmInfo>($"select * from alarms where  AlarmCode='{code}' and AlarmContent='{content}' and StartTime is not null " +
                        $"and StartTime<>'' And (EndTime is null or EndTime='') ").FirstOrDefault();
                    if (entity != null)
                    {
                        entity.EndTime = endTime;
                        db.Update(entity);
                        result = true;
                    }
                    else if (entity == null && !string.IsNullOrWhiteSpace(startTime) && DateTime.TryParse(startTime, out time))
                    {
                        db.Insert(new AlarmInfo()
                        {
                            AlarmCode = code,
                            AlarmContent = content,
                            StartTime = startTime,
                            EndTime = endTime
                        });
                        result = true;
                    }
                }
            }
            return result;
        }
    }

}
